package com.chd.driversystem.gen;

import android.util.Log;

import com.chd.driversystem.domain.DrivingRecord;
import com.chd.driversystem.domain.Evaluation;
import com.chd.driversystem.domain.Oil;
import com.chd.driversystem.domain.Operation;
import com.chd.driversystem.domain.Ranking;
import com.chd.driversystem.domain.User;
import com.chd.driversystem.domain.Vehicle;
import com.chd.driversystem.util.tools.LogUtil;
import com.chd.driversystem.util.tools.MyApplication;

import java.util.List;

/**
 * Created by feiyu on 17-5-12.
 */

public class BeanServer {
    private static final String TAG = "BeanServer";
    private static BeanServer beanServer;

    private AssignmentDao assignmentDao;
    private DrivingRecordDao drivingRecordDao;
    private EvaluationDao evaluationDao;
    private OilDao oilDao;
    private OperationDao operationDao;
    private TeamDao teamDao;
    private UserDao userDao;
    private VehicleDao vehicleDao;
    private RankingDao rankingDao;

    private BeanServer() {
        DaoSession daoSession = GreenDaoManager.getInstance().getSession();
        assignmentDao = daoSession.getAssignmentDao();
        drivingRecordDao = daoSession.getDrivingRecordDao();
        evaluationDao = daoSession.getEvaluationDao();
        oilDao = daoSession.getOilDao();
        operationDao = daoSession.getOperationDao();
        teamDao = daoSession.getTeamDao();
        userDao = daoSession.getUserDao();
        vehicleDao = daoSession.getVehicleDao();
        rankingDao = daoSession.getRankingDao();
    }

    public static BeanServer getInstance() {
        if (beanServer == null) {
            synchronized (GreenDaoManager.class) {
                if (beanServer == null) {
                    beanServer = new BeanServer();
                }
            }
        }
        return beanServer;
    }

    public Long saveUser(User user) {
        Long id = -1L;
        User tmp = userDao.queryBuilder()
                .where(UserDao.Properties.Code.eq(user.getCode()))
                .build().unique();
        if (tmp != null) {
            id = tmp.getId();
            user.setId(id);
            userDao.update(user);
        } else {
            id = userDao.insert(user);
        }
        return id;
    }

    public Long saveDrivingRecord(DrivingRecord drivingRecord) {
        Long id = -1L;
        DrivingRecord tmp = drivingRecordDao.queryBuilder()
                .where(DrivingRecordDao.Properties.CreateDate.eq(drivingRecord.getCreateDate()),
                        DrivingRecordDao.Properties.UserId.eq(drivingRecord.getUserId()))
                .unique();
        if (tmp != null) {  //代表数据库已有用户信息
            id = tmp.getId();
            drivingRecord.setId(id);
            drivingRecordDao.update(drivingRecord);
        } else {
            id = drivingRecordDao.insert(drivingRecord);
        }
        LogUtil.d(TAG, "saveDrivingRecord: id" + id + "; size = " + drivingRecordDao.count());
        return id;
    }

    public Long saveEvaluation(Evaluation evaluation) {
        Long id = -1L;
        Evaluation tmp = evaluationDao.queryBuilder()
                .where(EvaluationDao.Properties.UserId.eq(evaluation.getUserId()),
                        EvaluationDao.Properties.Type.eq(evaluation.getType()),
                        EvaluationDao.Properties.CreateDate.eq(evaluation.getCreateDate()))
                .build()
                .unique();
        if (tmp == null) {
            id = evaluationDao.insert(evaluation);
        }
        LogUtil.d(TAG, "saveEvaluation: id" + id + "; size = " + evaluationDao.count());
        return id;
    }

    public Long saveVehicle(Vehicle veh) {
        Long id = -1L;
        Vehicle tmp = vehicleDao.queryBuilder()
                .where(VehicleDao.Properties.UserId.eq(veh.getUserId()))
                .build()
                .unique();
        if (tmp != null) {
            id = tmp.getId();
            veh.setId(id);
            vehicleDao.update(veh);
        } else {
            id = vehicleDao.insert(veh);
        }
        LogUtil.d(TAG, "saveVehicle: id" + id + "; size = " + vehicleDao.count());
        return id;
    }

    public Long saveOperation(Operation operation) {
        Long id = -1L;
        Operation tmp = operationDao.queryBuilder()
                .where(OperationDao.Properties.UserId.eq(operation.getUserId()),
                        OperationDao.Properties.CreateDate.eq(operation.getCreateDate()))
                .build().unique();
        if (tmp != null) {
            id = tmp.getId();
            operation.setId(id);
            operationDao.update(operation);
        } else {
            id = operationDao.insert(operation);
        }
        LogUtil.d(TAG, "saveOperation: id" + id + "; size = " + operationDao.count());
        return id;
    }

    public Long saveOil(Oil oil) {
        Long id = -1L;
        Oil tmp = oilDao.queryBuilder()
                .where(OilDao.Properties.UserId.eq(oil.getUserId()),
                        OilDao.Properties.CreateDate.eq(oil.getCreateDate()))
                .build().unique();
        if (tmp != null) {
            id = tmp.getId();
            oil.setId(id);
            oilDao.update(oil);
        } else {
            id = oilDao.insert(oil);
        }
        LogUtil.d(TAG, "saveOil: id" + id + "; size = " + oilDao.count());
        return id;
    }

    public int saveOilList(List<Oil> oils) {
        int count = 0;
        for (Oil oil : oils) {
            Oil tmp = oilDao.queryBuilder()
                    .where(OilDao.Properties.UserId.eq(oil.getUserId()),
                            OilDao.Properties.CreateDate.eq(oil.getCreateDate()))
                    .build().unique();
            if (tmp != null) {
                boolean flag = false;
                if (tmp.getFuel() != oil.getFuel() && oil.getFuel() > 0) {
                    tmp.setFuel(oil.getFuel());
                    flag = true;
                }
                if (tmp.getOilLevel() != oil.getOilLevel() && oil.getOilLevel() > 0) {
                    tmp.setOilLevel(oil.getOilLevel());
                    flag = true;
                }
                if (tmp.getAveFuel() != oil.getAveFuel() && oil.getAveFuel() > 0) {
                    tmp.setAveFuel(oil.getAveFuel());
                    flag = true;
                }
                if (tmp.getTotalFuel() != oil.getTotalFuel() && oil.getTotalFuel() > 0) {
                    tmp.setTotalFuel(oil.getTotalFuel());
                    flag = true;
                }
                if (flag) {
                    count++;
                    oilDao.update(tmp);
                }
            } else {
                long insert = oilDao.insert(oil);
                if (insert > 0)
                    count++;
            }
        }
        LogUtil.d(TAG, "saveOilList: count" + count + "; size = " + oilDao.count());
        return count;
    }

    public User getUserById(Long id) {
        User user = userDao.loadByRowId(id);
        LogUtil.d(TAG, "saveUser: id" + id + "; size = " + userDao.count());
        return user;
    }

    public User getUserByCodeAndPassword(String loginname, String password) {
        LogUtil.d(TAG, "getUserByCodeAndPassword() called with: loginname = [" + loginname + "], " +
                "password = [" + password + "]");
        User user = userDao.queryBuilder()
                .where(UserDao.Properties.Code.eq(loginname),
                        UserDao.Properties.Password.eq(password))
                .build().unique();
        return user;
    }

    public Long getUserSize() {
        return userDao.queryBuilder()
                .where(UserDao.Properties.IsManager.eq(false),
                        UserDao.Properties.ManagerId.eq(MyApplication.getUser().getId()))
                .count();
    }

    public List<Evaluation> getEvaluationsByType(Long userId, int type) {
        LogUtil.d(TAG, "getEvaluationsByType: userId" + userId);
        return evaluationDao.queryBuilder()
                .where(EvaluationDao.Properties.UserId.eq(userId),
                        EvaluationDao.Properties.Type.eq(type))
                .orderAsc(EvaluationDao.Properties.CreateDate)
                .limit(30)
                .build().list();
    }

    public Long saveEvaluations(List<Evaluation> evaluations) {
        Long count = 0L;
        for (Evaluation evaluation : evaluations) {
            Evaluation tmp = evaluationDao.queryBuilder()
                    .where(EvaluationDao.Properties.UserId.eq(evaluation.getUserId()),
                            EvaluationDao.Properties.Type.eq(evaluation.getType()),
                            EvaluationDao.Properties.CreateDate.eq(evaluation.getCreateDate()))
                    .build().unique();
            if (tmp == null) {
                if (evaluationDao.insert(evaluation) > 0)
                    count++;
            } else {
                evaluation.setId(tmp.getId());
                evaluationDao.update(evaluation);
                count++;
            }
        }
        LogUtil.d(TAG, "saveEvaluations: count = " + count + " ; size = " + evaluationDao.count());
        return count;
    }

    public Evaluation getLastEvaluationByType(Long userId, int type) {
        Evaluation evaluation = evaluationDao.queryBuilder()
                .where(EvaluationDao.Properties.UserId.eq(userId),
                        EvaluationDao.Properties.Type.eq(type))
                .orderDesc(EvaluationDao.Properties.CreateDate)
                .limit(1)
                .build().unique();
        return evaluation;
    }

    public long getCountEvaByRange(int start, int end) {
        LogUtil.d(TAG, "getCountEvaByRange() called with: start = [" + start + "], end = [" + end + "]");
        return evaluationDao.queryBuilder()
                .where(EvaluationDao.Properties.TScore.between(start, end))
                .count();
    }

    public Oil getOilLastByUserId(Long userId) {
        Oil oil = oilDao.queryBuilder()
                .where(OilDao.Properties.UserId.eq(userId))
                .orderDesc(OilDao.Properties.CreateDate)
                .limit(1)
                .build()
                .unique();
        return oil;
    }

    public int saveUserList(List<User> users) {
        int count = 0;
        for (User user : users) {
            User tmp = userDao.queryBuilder()
                    .where(UserDao.Properties.Code.eq(user.getCode()))
                    .build().unique();
            if (tmp != null) {
                user.setId(tmp.getId());
                userDao.update(user);
            } else {
                userDao.insert(user);
                count++;
            }
        }
        return count;
    }

    public DrivingRecord getLastDrivingRecordByUserId(Long id) {
        DrivingRecord drivingRecord = drivingRecordDao.queryBuilder()
                .where(DrivingRecordDao.Properties.UserId.eq(id))
                .orderDesc(DrivingRecordDao.Properties.CreateDate)
                .limit(1)
                .unique();
        return drivingRecord;
    }

    public List<Ranking> getRankings() {
        return rankingDao.queryBuilder()
                .orderDesc(RankingDao.Properties.Score)
                .build()
                .list();
    }

    public List<User> getDriverUsers() {
        return userDao.queryBuilder()
                .where(UserDao.Properties.IsManager.eq(false))
                .build()
                .list();
    }

    public Long saveRanking(Ranking ranking) {
        Long id = -1L;
        Ranking tmp = rankingDao.queryBuilder()
                .where(RankingDao.Properties.UserId.eq(ranking.getUserId()))
                .build().unique();
        if (tmp != null) {
            if (tmp.getScore().equals(ranking.getScore())) {
                id = tmp.getId();
                ranking.setId(id);
                rankingDao.update(ranking);
            }
        } else {
            id = rankingDao.insert(ranking);
        }
        return id;
    }

    public Operation getLastOperationByUserId(Long id) {
        Operation operation = operationDao.queryBuilder()
                .where(OperationDao.Properties.UserId.eq(id))
                .orderDesc(OperationDao.Properties.CreateDate)
                .limit(1)
                .unique();
        return operation;
    }

    public Ranking getRankingByUserId(Long userId) {
        return rankingDao.queryBuilder()
                .where(RankingDao.Properties.UserId.eq(userId))
                .build()
                .unique();
    }

    public User getUserByCode(String driverId) {
        return userDao.queryBuilder()
                .where(UserDao.Properties.Code.eq(driverId))
                .build().unique();
    }

    public int saveDrivingRecord(List<DrivingRecord> drivingRecords) {
        int count = 0;
        for (DrivingRecord drivingRecord : drivingRecords) {
            DrivingRecord tmp = drivingRecordDao.queryBuilder()
                    .where(DrivingRecordDao.Properties.UserId.eq(drivingRecord.getUserId()),
                            DrivingRecordDao.Properties.CreateDate.eq(drivingRecord.getCreateDate()))
                    .build().unique();
            if (tmp != null) {
                boolean flag = false;
                if (tmp.getTDistance() != drivingRecord.getTDistance() && drivingRecord.getTtOverspeed() > 0) {
                    tmp.setTDistance(drivingRecord.getTDistance());
                    flag = true;
                }
                if (tmp.getTtOverspeed() != drivingRecord.getTtOverspeed() && drivingRecord.getTtOverspeed() > 0) {
                    tmp.setTtOverspeed(drivingRecord.getTtOverspeed());
                    flag = false;
                }
                if (tmp.getSfDriving() != drivingRecord.getSfDriving() && drivingRecord.getSfDriving() > 0) {
                    tmp.setSfDriving(drivingRecord.getSfDriving());
                    flag = true;
                }
                if (tmp.getCfDriving() != drivingRecord.getCfDriving() && drivingRecord.getCfDriving() > 0) {
                    tmp.setCfDriving(drivingRecord.getCfDriving());
                    flag = false;
                }
                if (tmp.getDistance() != drivingRecord.getDistance() && drivingRecord.getDistance() > 0) {
                    tmp.setDistance(drivingRecord.getDistance());
                    flag = true;
                }
                if (tmp.getTtDriving() != drivingRecord.getTtDriving() && drivingRecord.getTtDriving() > 0) {
                    tmp.setTtDriving(drivingRecord.getTtDriving());
                    flag = false;
                }
                if (tmp.getAveSpeed() != drivingRecord.getAveSpeed() && drivingRecord.getAveSpeed() > 0) {
                    tmp.setAveSpeed(drivingRecord.getAveSpeed());
                    flag = true;
                }
                if (tmp.getMaxSpeed() != drivingRecord.getMaxSpeed() && drivingRecord.getMaxSpeed() > 0) {
                    tmp.setMaxSpeed(drivingRecord.getMaxSpeed());
                    flag = false;
                }
                if (flag) {
                    count++;
                    drivingRecordDao.update(tmp);
                }
            } else {
                long insert = drivingRecordDao.insert(drivingRecord);
                if (insert > 0)
                    count++;
            }
        }
        return count;
    }

    public int saveOperations(List<Operation> operations) {
        int count = 0;
        for (Operation operation : operations) {
            Operation tmp = operationDao.queryBuilder()
                    .where(OperationDao.Properties.UserId.eq(operation.getUserId()),
                            OperationDao.Properties.CreateDate.eq(operation.getCreateDate()))
                    .build().unique();
            if (tmp != null) {
                boolean flag = false;
                if (tmp.getBrake() != operation.getBrake() && operation.getBrake() > 0) {
                    tmp.setBrake(operation.getBrake());
                    flag = true;
                }
                if (tmp.getShift() != operation.getShift() && operation.getShift() > 0) {
                    tmp.setShift(operation.getShift());
                    flag = false;
                }
                if (tmp.getRapidAcc() != operation.getRapidAcc() && operation.getRapidAcc() > 0) {
                    tmp.setRapidAcc(operation.getRapidAcc());
                    flag = true;
                }
                if (tmp.getRapidDec() != operation.getRapidDec() && operation.getRapidDec() > 0) {
                    tmp.setRapidDec(operation.getRapidDec());
                    flag = false;
                }
                if (tmp.getRpm() != operation.getRpm() && operation.getRpm() > 0) {
                    tmp.setRpm(operation.getRpm());
                    flag = true;
                }

                if (flag) {
                    count++;
                    operationDao.update(tmp);
                }
            } else {
                long insert = operationDao.insert(operation);
                if (insert > 0)
                    count++;
            }
        }
        return count;
    }
}
